import java.math.BigInteger;
import java.security.SecureRandom;


public class BlindSignature {
	
	private BigInteger k = null;
	private BigInteger gcd = null;
	private BigInteger one = null;
	
	public BlindSignature(){
	}
	
	public BigInteger generateRandom(BigInteger modules) throws Exception{
		//*********************** SETUP **********************************
        
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG","SUN");
        byte [] randomBytes = new byte[10];
        k = null;
        gcd = null;
        one = new BigInteger("1");

        do {
            random.nextBytes(randomBytes);
            k = new BigInteger(randomBytes);
            gcd = k.gcd(modules);
        }
        while(!gcd.equals(one) || k.compareTo(modules)>=0 || k.compareTo(one)<=0);
        
        return k;
	}
	
	public BigInteger blindSignature(BigInteger random, BigInteger pubKey, BigInteger modules, BigInteger message){
		System.out.println("blindSignature = " + ((random.modPow(pubKey,modules)).multiply(message)).mod(modules));
        return ((random.modPow(pubKey,modules)).multiply(message)).mod(modules);
	}
	
	public BigInteger signSignature(BigInteger blind, BigInteger privKey, BigInteger modules){
		System.out.println("signSignature = " + blind.modPow(privKey,modules));
        return blind.modPow(privKey,modules);
	}
	
	public BigInteger unblindSignature(BigInteger random, BigInteger blindSignature, BigInteger modules){
		System.out.println("unblindSignature = " + random.modInverse(modules).multiply(blindSignature).mod(modules));
        return random.modInverse(modules).multiply(blindSignature).mod(modules);
	}
	
	public Boolean verifiedSignature(BigInteger Signature, BigInteger publicKey, BigInteger modules, BigInteger message){
		System.out.println("Signature = " + Signature);
		System.out.println("verifiedSignature = " + message.modPow(publicKey,modules));
        return message.equals(Signature.modPow(publicKey,modules));
	}
}
